{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": []
    }
   ],
   "source": [
    "import pandas as pd # type: ignore\n",
    "\n",
    "df = pd.read_csv(\n",
    "    \"../data/course-5-boston.csv\"\n",
    ")\n",
    "df.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [
    {
     "data": {},
     "execution_count": 56,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "features = df[[\"crim\", \"rm\", \"lstat\"]]\n",
    "features.describe()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [
    {
     "data": {},
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "target = df[\"medv\"]  # 目标值数据\n",
    "\n",
    "# 70% 训练集，30% 测试集\n",
    "\n",
    "split_num = int(len(features) * 0.7)  # 得到 70% 位置\n",
    "\n",
    "X_train = features[:split_num]  # 训练集特征\n",
    "y_train = target[:split_num]  # 训练集目标\n",
    "\n",
    "X_test = features[split_num:]  # 测试集特征\n",
    "y_test = target[split_num:]  # 测试集目标\n",
    "\n",
    "X_train.shape, y_train.shape, X_test.shape, y_test.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [
    {
     "data": {},
     "execution_count": 58,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.linear_model import LinearRegression # type: ignore\n",
    "\n",
    "model = LinearRegression()  # 建立模型\n",
    "model.fit(X_train, y_train)  # 训练模型\n",
    "model.coef_, model.intercept_  # 输出训练后的模型参数和截距项"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [
    {
     "data": {},
     "execution_count": 59,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "preds = model.predict(X_test)  # 输入测试集特征进行预测\n",
    "preds  # 预测结果"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这段代码的主要功能是将数据集分为训练集和测试集，通常用于机器学习模型的训练和评估。以下是代码的详细解析和示例：\n",
    "\n",
    "---\n",
    "\n",
    "### 1. **目标值数据提取**\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [],
   "source": [
    "target = df[\"medv\"]  # 目标值数据"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- **作用**: 从数据框 `df` 中提取目标变量（`medv` 列），并将其存储在变量 `target` 中。\n",
    "- **背景**: `medv` 通常是一个回归问题中的目标变量，例如波士顿房价数据集中，`medv` 表示房屋的中位价格。\n",
    "- **示例**:\n",
    "  假设 `df` 是以下数据框：\n",
    "  ```python\n",
    "  import pandas as pd\n",
    "  data = {\n",
    "      \"rm\": [6.5, 7.2, 6.8, 5.9],\n",
    "      \"medv\": [24.0, 27.5, 22.8, 19.6]\n",
    "  }\n",
    "  df = pd.DataFrame(data)\n",
    "  ```\n",
    "  则 `target` 的值为：\n",
    "  ```python\n",
    "  target = df[\"medv\"]\n",
    "  # target: [24.0, 27.5, 22.8, 19.6]\n",
    "  ```\n",
    "\n",
    "---\n",
    "\n",
    "### 2. **划分训练集和测试集的比例**\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [],
   "source": [
    "split_num = int(len(features) * 0.7)  # 得到 70% 位置"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- **作用**: 计算数据集中 70% 的位置索引，用于划分训练集和测试集。\n",
    "- **背景**: 通常在机器学习中，数据集会按照一定比例划分为训练集和测试集，70% 用于训练，30% 用于测试是常见的划分方式。\n",
    "- **示例**:\n",
    "  假设 `features` 有 10 条记录：\n",
    "  ```python\n",
    "  features = list(range(10))  # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n",
    "  split_num = int(len(features) * 0.7)  # 10 * 0.7 = 7\n",
    "  # split_num: 7\n",
    "  ```\n",
    "\n",
    "---\n",
    "\n",
    "### 3. **划分训练集和测试集**\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {},
   "outputs": [],
   "source": [
    "X_train = features[:split_num]  # 训练集特征\n",
    "y_train = target[:split_num]  # 训练集目标\n",
    "\n",
    "X_test = features[split_num:]  # 测试集特征\n",
    "y_test = target[split_num:]  # 测试集目标"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- **作用**: 根据 `split_num` 将数据集划分为训练集和测试集。\n",
    "  - `X_train` 和 `y_train` 是训练集的特征和目标值。\n",
    "  - `X_test` 和 `y_test` 是测试集的特征和目标值。\n",
    "- **背景**: 训练集用于训练模型，测试集用于评估模型的性能。\n",
    "- **示例**:\n",
    "  假设 `features` 和 `target` 如下：\n",
    "  ```python\n",
    "  features = [[1], [2], [3], [4], [5], [6], [7], [8], [9], [10]]\n",
    "  target = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]\n",
    "  split_num = 7\n",
    "  ```\n",
    "  则划分结果为：\n",
    "  ```python\n",
    "  X_train = features[:split_num]  # [[1], [2], [3], [4], [5], [6], [7]]\n",
    "  y_train = target[:split_num]    # [10, 20, 30, 40, 50, 60, 70]\n",
    "\n",
    "  X_test = features[split_num:]  # [[8], [9], [10]]\n",
    "  y_test = target[split_num:]    # [80, 90, 100]\n",
    "  ```\n",
    "\n",
    "---\n",
    "\n",
    "### 4. **检查数据形状**\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {},
   "outputs": [
    {
     "data": {},
     "execution_count": 63,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X_train.shape, y_train.shape, X_test.shape, y_test.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- **作用**: 检查训练集和测试集的特征和目标值的形状，确保划分正确。\n",
    "- **背景**: `.shape` 是 NumPy 数组或 Pandas 数据框的属性，用于返回数据的维度信息。\n",
    "- **示例**:\n",
    "  假设 `X_train` 和 `y_train` 是 NumPy 数组：\n",
    "  ```python\n",
    "  import numpy as np\n",
    "  X_train = np.array([[1], [2], [3], [4], [5], [6], [7]])\n",
    "  y_train = np.array([10, 20, 30, 40, 50, 60, 70])\n",
    "  ```\n",
    "  则：\n",
    "  ```python\n",
    "  X_train.shape  # (7, 1)\n",
    "  y_train.shape  # (7,)\n",
    "  ```\n",
    "\n",
    "---\n",
    "\n",
    "### 总结\n",
    "这段代码的核心是将数据集按照 70% 和 30% 的比例划分为训练集和测试集，便于后续的模型训练和评估。通过示例可以看出，代码逻辑清晰，适用于大多数机器学习任务中的数据预处理步骤。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": []
    }
   ],
   "source": [
    "import numpy as np # type: ignore\n",
    "\n",
    "x = np.array([56, 72, 69, 88, 102, 86, 76, 79, 94, 74])\n",
    "y = np.array([92, 102, 86, 110, 130, 99, 96, 102, 105, 92])\n",
    "\n",
    "\n",
    "def mae_solver(y_true: np.ndarray, y_pred: np.ndarray):\n",
    "    \"\"\"MAE 求解\"\"\"\n",
    "    n = len(y_true)\n",
    "    mae = sum(np.abs(y_true - y_pred)) / n\n",
    "    return mae\n",
    "\n",
    "def mse_solver(y_true: np.ndarray, y_pred: np.ndarray):\n",
    "    \"\"\"MSE 求解\"\"\"\n",
    "    n = len(y_true)\n",
    "    mse = sum(np.square(y_true - y_pred)) / n\n",
    "    return mse\n",
    "\n",
    "mae = mae_solver(y_test.values, preds)\n",
    "mse = mse_solver(y_test.values, preds)\n",
    "\n",
    "print(\"MAE: \", mae)\n",
    "print(\"MSE: \", mse)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": []
    }
   ],
   "source": [
    "from sklearn.metrics import mean_absolute_error, mean_squared_error\n",
    "\n",
    "mae_ = mean_absolute_error(y_test, preds)\n",
    "mse_ = mean_squared_error(y_test, preds)\n",
    "\n",
    "print(\"scikit-learn MAE: \", mae_)\n",
    "print(\"scikit-learn MSE: \", mse_)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": ".venv",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
